Skip to content

feat(tracing): add DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT#3997

Draft
MilanGarnier wants to merge 11 commits into
masterfrom
MilanGarnier/propagation-behavior-extract
Draft

feat(tracing): add DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT#3997
MilanGarnier wants to merge 11 commits into
masterfrom
MilanGarnier/propagation-behavior-extract

Conversation

@MilanGarnier

Copy link
Copy Markdown

Summary

Implements DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT (APMAPI-1941, feature-parity #353) for the PHP tracer, matching behavior already present in .NET, Python, Node, Java, Ruby, and Rust.

Three values:

  • continue (default): inherit upstream trace context unchanged — no behavior change
  • restart: start a fresh trace; the upstream context is captured as a span link with reason=propagation_behavior_extract
  • ignore: drop all extracted context including baggage and sampling priority

Design:

  • Single chokepoint: all extraction funnels through ddtrace_apply_distributed_tracing_result in distributed_tracing_headers.c, covering both request-init and consume_distributed_tracing_headers userland calls
  • restart path: when the root span doesn't yet exist at request-init time, the span link is queued in DDTRACE_G(pending_upstream_span_link) and consumed in ddtrace_open_span when the root span is created
  • Extracted ddtrace_build_span_link_from_result() from SpanLink::fromHeaders for reuse

Test plan

  • tests/ext/distributed_tracing/propagation_behavior_extract_continue.phpt — verifies trace_id inherited, no span link, baggage preserved
  • tests/ext/distributed_tracing/propagation_behavior_extract_restart.phpt — verifies fresh trace_id, span link with correct upstream ids and reason, baggage preserved, _dd.p.* not in link attributes
  • tests/ext/distributed_tracing/propagation_behavior_extract_ignore.phpt — verifies fresh trace_id, no span link, baggage dropped, sampling priority dropped
  • tests/ext/distributed_tracing/propagation_behavior_extract_config.phpt — verifies case-insensitive parsing, invalid value falls back to continue
  • CI phpt suite

Related

  • APMAPI-1941
  • Ruby: dd-trace-rb#5844
  • Rust: dd-trace-rs#248

🤖 Generated with Claude Code

@MilanGarnier MilanGarnier added the AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos label Jun 17, 2026
@datadog-official

datadog-official Bot commented Jun 17, 2026

Copy link
Copy Markdown

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 54.12% (+0.00%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: c7674bd | Docs | Datadog PR Page | Give us feedback!

MilanGarnier and others added 5 commits June 17, 2026 17:11
Adds the new `DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT` config key (values:
continue, restart, ignore) with a CUSTOM(INT) parser, the corresponding
C enum, and the supported-configurations.json entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds three behaviors at the single extraction chokepoint
(ddtrace_apply_distributed_tracing_result):

- continue (default): inherit upstream trace context unchanged
- restart: start a fresh trace; upstream captured as a span link with
  reason=propagation_behavior_extract. When the root span doesn't exist
  yet at request-init time, the link is queued in
  DDTRACE_G(pending_upstream_span_link) and attached in ddtrace_open_span.
- ignore: drop all extracted context including baggage and sampling priority

Also extracts ddtrace_build_span_link_from_result() from the SpanLink
fromHeaders method so it can be reused by the restart path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the three behaviors (continue, restart, ignore) and config
parsing (case-insensitive values, invalid value falls back to default).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@MilanGarnier MilanGarnier force-pushed the MilanGarnier/propagation-behavior-extract branch from 6b7e259 to 3ca8428 Compare June 17, 2026 15:33
Comment thread tracer/distributed_tracing_headers.c Outdated
Comment thread tracer/distributed_tracing_headers.c Outdated

if (behavior == DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT_RESTART && (result->trace_id.low || result->trace_id.high)) {
// behavior=restart: zero trace_id so a fresh trace starts; upstream captured as span link
// drop _dd.p.* first so the builder does not include them in link attributes

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would we want to drop e.g. _dd.p.usr.id? Shouldn't that be an useful attribute to see?

@MilanGarnier MilanGarnier Jun 18, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand it, the role of this feature is to explicitly discard all incoming tags other than baggage. That way, let's say it is a service extracting a trace coming from outside, it can decide to restart a trace in its own terms (own sampling decision and everything else). That being said, I am new on the subject so I'll look again in other tracers

@bwoebi bwoebi Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But, if it's only baggage what you want, you only need result->baggage (which is handled below for you) and ignore result->meta_tags completely (simply clean), which are the tracer tags, like x-datadog-tags and tracestate equivalent.

Comment thread tracer/functions.c
}
ddtrace_build_span_link_from_result(&result, link);

result.meta_tags.pDestructor = NULL; // we moved values directly

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You did not like the do-not-touch-the-refcount approach? :-) Seeing you susbtituted it for zval_add_ref copying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants